defmodule IocpMonitor.Controller.RealtimeDataController do
  @moduledoc """
  实时数据解析Controller。
  解析完毕的数据入列`IocpMonitor.Dumper.Queue`，
  以便在系统资源可用的时候保存该数据。
  """

  @behaviour IocpMonitor.Controller

  use Bitwise

  import IocpMonitor.LittleEndian
  alias IocpMonitor.Schemas.IocpLog
  alias IocpMonitor.Worker.DataBuffer

  @impl true
  def handle(device_address, [
    second, minute, hour,
    day, month, year,
    voltage_lo, voltage_hi,
    amperage_lo, amperage_hi,
    power_lo, power_hi,
    consumption_0, consumption_1, consumption_2, consumption_3,
    warning_flags | _
  ]) do
    observed_at = {{year + 2000, month, day}, {hour, minute, second}}
                  |> NaiveDateTime.from_erl!()

    voltage = to_i([voltage_lo, voltage_hi])
    amperage = to_i([amperage_lo, amperage_hi])
    power = to_i([power_lo, power_hi])
    consumption = to_i([consumption_0, consumption_1, consumption_2, consumption_3])

    overcurrent1 = (warning_flags &&& 1) != 0
    overcurrent2 = (warning_flags &&& 2) != 0
    overvoltage  = (warning_flags &&& 4) != 0
    undervoltage = (warning_flags &&& 8) != 0

    dump(device_address, %IocpLog{
      device_address: device_address,
      observed_at: observed_at,
      voltage: voltage,
      amperage: amperage,
      power: power,
      consumption: consumption,
      overcurrent1: (if overcurrent1, do: 1, else: 0),
      overcurrent2: (if overcurrent2, do: 1, else: 0),
      overvoltage: (if overvoltage, do: 1, else: 0),
      undervoltage: (if undervoltage, do: 1, else: 0)
    })
  end

  defp dump(device_address, data) do
    # BlockingQueue.push(BlockingQueue, data)
    DataBuffer.push(device_address, data)
  end
end
